package core

import (
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"net/http"
	"time"
)

type ProjShellRunner struct {
	utils.SubscribeCenter
	plugId   string
	cmdCache *wrapper.SuperValue
}

func (this *ProjShellRunner) SetPlugID(val string) {
	this.plugId = val
}

/*
*

	?id=update-me&wait-secs=5

tag:0 所有

	1: 只列出文件夹
	2: 只列出文件
*/
func (this *ProjShellRunner) OnHttpDo(rec *PlgHttpRec) (rval interface{}, errcode int, err error) {
	if this.cmdCache == nil || this.cmdCache.Count() == 0 {
		rec.ResponseJSONValues("code", -1, "errcode", 404, "msg", "没有指定命令集合！")
		return
	}
	strid := rec.QryAsString("id", "")
	cmd := this.cmdCache.ValueByName(strid)
	if cmd == nil {
		http.Error(rec.RespW, "cmd is not found!", 503)
		return
	}
	cmdline := cmd.StringByName("cmd-line", "")
	if len(cmdline) == 0 {
		return nil, 404, fmt.Errorf("[%s] cmd-line is empty", strid)
	}

	cmdline = ReplacePlaceholderForFileName(cmdline)
	secs := time.Duration(rec.QryAsInt("wait-secs", 0)) * time.Second

	if secs <= 0 {
		secs = time.Second * 30
	}

	utils.ExecTimeOut(func() {
		utils.Log.InfoTypef(this.plugId, "准备执行命令:%s", cmdline)
		err = utils.ExecShell(cmdline)
		if err != nil {
			utils.Log.InfoTypef(this.plugId, "执行命令(%s)异常:%s", cmdline, err.Error())
		}
	}, secs)

	if err != nil {
		return nil, 503, err
	}

	rec.ResponseJSONValues("code", 0)

	return
}

/*
*

	{
	  "id":"upload",
	  "type":"core.shellrunner",
	  "conf":{
	    "delay-secs":10,
	    "cmd-line":"cd $approot$&&rm -rf up-kpl-gnss-centos.sh&&wget http://119.96.169.117:3000/kpl-release/up-kpl-gnss-centos.sh&&chmod +x up-kpl-gnss-centos.sh&&./up-kpl-gnss-centos.sh",
	    "cache":[
	       {"id":"update-me", "cmd-line":""}
	     ]
	  }
	}
*/
func (this *ProjShellRunner) ReloadConf(conf *wrapper.SuperValue) error {
	if this.cmdCache == nil {
		this.cmdCache = wrapper.NewSVObject()
	}
	cache := conf.ValueByName("cache")
	if cache != nil {
		cache.Range(func(key string, val *wrapper.SuperValue) bool {
			if len(key) == 0 {
				key = val.StringByName("id", "")
			}
			this.cmdCache.SetKeyValue(key, val)
			return true
		})
	}

	cmdline := conf.StringByName("cmd-line", "")
	if len(cmdline) > 0 {
		cmdline = ReplacePlaceholderForFileName(cmdline)
		delay := conf.IntByName("delay-secs", 0)
		if delay > 0 {
			time.AfterFunc(time.Second*time.Duration(delay), func() {
				utils.Log.InfoTypef(this.plugId, "准备执行命令:%s", cmdline)
				err := utils.ExecShellAndNoWait(cmdline)
				if err != nil {
					utils.Log.InfoTypef(this.plugId, "执行命令(%s)异常:%s", cmdline, err.Error())
				}
			})
		} else {
			utils.ExecTimeOut(func() {
				utils.Log.InfoTypef(this.plugId, "准备执行命令:%s", cmdline)
				err := utils.ExecShellAndNoWait(cmdline)
				if err != nil {
					utils.Log.InfoTypef(this.plugId, "执行命令(%s)异常:%s", cmdline, err.Error())
				}
			}, time.Second)
		}
	}

	return nil
}

func (this *ProjShellRunner) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		} else {
			err = fmt.Errorf("非法的JSON配置")
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {

	}
	return
}

func CreateProjShellRunnerFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ProjShellRunner{}
	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.plugId = str
		}
	}
	rval = obj
	return
}
